/***ModuleBase By GYLite 2022-12-26
 * 定义了模块基类的结构，所有模块需继承此类获得模块功能
*/
class ModuleBase extends GYLite.GYUIComponent {	
	public uiPath: string;
	public uiID: string;
	public url: string;
	public uiData: UICtrlData;	
	protected _baseData: any;	
	protected _scaleMode: string;
    protected _stageSize:boolean;	
	protected _moduleScale: number;
	protected _designWidth: number;
	protected _designHeight: number;
	protected _designScale:number;
	protected _designMaxRatio:number;
	protected _designMinRatio:number;
	protected _costCount:number;
	protected _aborted:boolean;
	protected _orientation:string;
    protected _offsetLeft:number;
    protected _offsetRight:number;
    protected _offsetTop:number;
    protected _offsetBottom:number;
	/**模块运行时产生的数据，可以附加到这个对象，通过Dispatch派发事件时(如Dispatch.MODULE_ABORT)，一并派发出去从而被外部接收到*/
	protected _module_data:any;
	protected _globalDispatcher:Dispatcher;
	public constructor() {
		super();
		let s = this;
		UIControl.getInstance().uiConstructorSet(this);	
		s._globalDispatcher = Dispatcher.getInstance();			
		s._costCount = 0;
		s._designScale = 1;
		s._designHeight = s._designWidth = NaN;
		s._scaleMode = null;
		s.width = GameManager.getInstance().stardardWidth;
		s.height = GameManager.getInstance().stardardHeight;		
		this.modulePreStart();
	}
	/**重新适配模块
	 * @param w 模块的设计尺寸 宽度
	 * @param h 模块的设计尺寸 高度
	 * @param scaleMode 适配方案参考LayerManager常量
	 * @param maxRatio 最宽的比例限制 默认NaN 无限制
	 * @param minRatio 最窄尺寸限制 默认1.333 4比3限制
	 * @param scale 设计的缩放比例，方便适配不同大小设备，前提是内容需要做成相对布局，否则会定位超出屏幕范围
	 * @param orientation 旋转方向
	 * @param stageSize 是否相对舞台(LayerManager.stageSp)适配，默认false，相对LayerManger.gameSp适配
	*/
	public resetSize(w: number, h: number, scaleMode: string, maxRatio: number = NaN, minRatio: number = 0.75,scale:number=1,orientation:string=null,stageSize:boolean=false): void {
		let s = this;		
		let shouldRotate:boolean;
		s._orientation = orientation;
		shouldRotate = s._orientation !=null && GYLite.GYSprite.stage.orientation != s._orientation;
		s._designMaxRatio = maxRatio;
		s._designMinRatio = minRatio;
		s._designScale = scale;
		s._designWidth = w;
		s._designHeight = h;
		s._stageSize = stageSize;
		w *= scale;
		h *= scale;
		s.width = w;
		s.height = h;
		let sclX: number, sclY: number, scl: number;
		let game: GameManager;
		let frameBound:egret.Rectangle;
		let stdW: number, stdH: number;
		let boundW:number,boundH:number;
		game = GameManager.getInstance();
		frameBound = LayerManager.getInstance().frameBound;
		boundW = stageSize?frameBound.width:game.stardardWidth;
		boundH = stageSize?frameBound.height:game.stardardHeight;
		s._scaleMode = scaleMode;
		scl = w / h;
		stdW = boundW;
		stdH = boundH;
		if (scl > maxRatio)
			stdW = h * maxRatio;
		else if (scl < minRatio)
			stdH = w / minRatio;

		if(shouldRotate)
		{
			sclX = stdH / w;
			sclY = stdW / h;
		}
		else
		{
			sclX = stdW / w;
			sclY = stdH / h;
		}
		

		if (s._scaleMode == LayerManager.FIX_WIDTH)
			s._moduleScale = sclX;
		else if (s._scaleMode == LayerManager.FIX_HEIGHT)
			s._moduleScale = sclY;
		else if (s._scaleMode == LayerManager.NOBORD)
			s._moduleScale = sclX > sclY ? sclX : sclY;
		else if (s._scaleMode == LayerManager.SHOWALL)
			s._moduleScale = sclX < sclY ? sclX : sclY;
		else
			s._moduleScale = 1;		
		s.scaleX = s.scaleY = s._moduleScale;
		if(shouldRotate)
		{
			s.rotation = -90;			
			s.x = (stageSize?frameBound.x:0) + (boundW - h * s._moduleScale >> 1);
			s.y = (stageSize?frameBound.y:0) + (boundH - w * s._moduleScale >> 1) + (w * s._moduleScale);
			s._offsetLeft = s._offsetRight = s.y - frameBound.y - (w * s._moduleScale);
			s._offsetTop = s._offsetBottom = s.x - frameBound.x;
		}
		else
		{			
			s.x = (stageSize?frameBound.x:0) + (boundW - w * s._moduleScale >> 1);
			s.y = (stageSize?frameBound.y:0) + (boundH - h * s._moduleScale >> 1);
			s._offsetLeft = s._offsetRight = s.x - frameBound.x;
			s._offsetTop = s._offsetBottom = s.y - frameBound.y
		}		
	}
	public get designScale():number
	{
		return this._designScale;
	}

	public set mode(val: number) {
		let s = this;
		s.uiData.mode = val;
		if (s.uiData.mode == LayerManager.MODE_INSCREEN && s.parent != LayerManager.getInstance().stageSp)
			LayerManager.getInstance().stageSp.addElement(s);
	}
	/**设置呈现的模式，参考LayerManager常量*/
	public get mode(): number {
		let s = this;
		return s.uiData ? s.uiData.mode : LayerManager.MODE_COMMON;
	}
	public setBackground(color: number, alpha: number): void {
		let s = this;
		LayerManager.getInstance().setBackground(color, alpha);
	}
	/**模块启动之前*/
	public modulePreStart(): void {
		let s = this;
		let userData: UserData = UserData.getInstance();
		let w: number, h: number;
		w = Number(userData.getQueryVariable("designWidth"));
		h = Number(userData.getQueryVariable("designHeight"));
		// Log.writeLog("designWidth：" + w + "-------------designHeight:" + h)
		if (w > 0 && h > 0)
			s.resetSize(w, h, LayerManager.FIX_WIDTH,s._designMaxRatio,s._designMinRatio,s._designScale);
		s.addEventListener(egret.Event.ADDED_TO_STAGE, s.addToStage, s);
	}
	protected addToStage(e: egret.Event): void {
		let s = this;
		if (s.uiData) s.uiData.moduleWatcher.moduleStart(s.start, s);
	}
	/**模块启动(addToStage的时候启动，重复添加到stage可多次启动)*/
	protected start(): void {
		let s = this;
		// if(s._baseData)
		// {
		// 	let s = this;
		// 	if(s._baseData.mask)
		// 	{
		// 		s.setBackground(s._baseData.maskColor!=null?s._baseData.maskColor:0xff0000,s._baseData.maskAlpha!=null?s._baseData.maskAlpha:1);
		// 	}
		// }
		s._aborted = false;
		s._startTimeOut = Date.now();
		GYLite.TimeManager.timeOut(s.enterIfOk, s, 100);
		// s.enterIfOk()
	}

	private _startTimeOut:number;
    

	/**场景就绪，过场拉开*/
	protected ready():void
	{

	}
	protected enterIfOk():void
	{let s = this;
		if(s.$disposed && s.stage == null)return;
		if(Log.costRender > 100 && s._costCount < 5 && Date.now() - s._startTimeOut < 1000)
		{
			++s._costCount;
			Log.writeLog("帧率低，等待进入：" + s._costCount,Log.WARN);
			GYLite.TimeManager.timeOut(s.enterIfOk, s, 200);
			return;
		}		
		s._costCount = 0;
		s._globalDispatcher.dispatchEventWith(Dispatcher.GAME_READY,false);		
		s.ready();	
	}	
	public show(pr: GYLite.GYSprite = null): void {
		let s = this;
		if (pr == null) {
			pr = (s.uiData && s.uiData.mode == LayerManager.MODE_INSCREEN) ? LayerManager.getInstance().stageSp : LayerManager.getInstance().uiLay;
		}
		if (s._baseData && s._baseData.interactOperateDataPath != null) {
			GameManager.getInstance().loadData(s._baseData.interactOperateDataPath, function (l: GYLite.LoadInfo): void {
				if (l.content) {
					pr.addElement(s);					
				}
				else
					Log.writeLog("操作数据下载失败！" + s._baseData.interactOperateDataPath, Log.WARN);
			}, s, null, GYLite.GYLoader.TYPE_JSON, HTTPConf.M_GET, { save: false }, false);
		}
		else {
			pr.addElement(s);			
		}
	}
	/**是否处于终止状态*/
	public get aborted():boolean
	{
		return this._aborted;
	}
	/**终止模块活动，当离开当前模块的环节时，主程序会调度此方法以通知模块进行活动停止*/
	public abort():void
	{
		let s = this;
		s._aborted = true;
		if(s._globalDispatcher.hasEventListener(Dispatcher.MODULE_ABORT))
		s._globalDispatcher.dispatchEventWith(Dispatcher.MODULE_ABORT, false, s._module_data);
	}

	public hide(): void {
		let s = this;
		if (s.parent)
		{
			(<any>s.parent).removeElement(s);
			if (s.uiData) s.uiData.moduleWatcher.moduleEnd();
			if(s._globalDispatcher.hasEventListener(Dispatcher.MODULE_HIDE))
				Dispatcher.getInstance().dispatchEventWith(Dispatcher.MODULE_HIDE, false, s._module_data);
		}			
	}

	public dispose(disposeChild: boolean = true, removeChild: boolean = true, forceDispose: boolean = false): void {
		super.dispose(disposeChild, removeChild, forceDispose);
		let s = this;
		let soundDict = SoundManager.instance.soundDict;		
		if (s.uiData) {
			for (let key in soundDict) {
				if (key.indexOf(s.uiData.uiPath.replace(/\./g, "/")) !== -1) {
					SoundManager.instance.dispose(key, true);
				}
			}
			s.uiData.clear();
		}		
		s.removeEventListener(egret.Event.ADDED_TO_STAGE, s.addToStage, s);
		if(s._module_data)
			s._module_data.uiCtrlData = null;
		s._module_data = s._globalDispatcher = null;		
	}

	public resize(w: number, h: number): void {
		let s = this;
		if (s._scaleMode)
			s.resetSize(s._designWidth, s._designHeight, s._scaleMode, s._designMaxRatio, s._designMinRatio, s._designScale);
	}
	public get designWidth():number
	{
		return this._designWidth;
	}
	public get designHeight():number
	{
		return this._designHeight;
	}

	public setData(d: any): void {
		let s = this;
		if(d == null)d = {};
		s._baseData = d;
		s._module_data = {uiCtrlData:s.uiData};
	}
	public getData(): any {		
		return this._baseData;
	}	

}